/*
 * @Author: 李超越 1509572300@qq.com
 * @Date: 2024-08-24 16:21:25
 * @LastEditors: 李超越 1509572300@qq.com
 * @LastEditTime: 2024-08-25 13:39:52
 * @FilePath: /my_git/lesson29_Cond/BlockQueue.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef __BLOCK_QUEUE_HPP__
#define __BLOCK_QUEUE_HPP__

#include "Thread.hpp"

template <typename T>
class BlockQueue
{
public:
    BlockQueue(int cap):_cap(cap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_product_cond, nullptr);
        pthread_cond_init(&_consum_cond, nullptr);
        _productor_wait_num = 0;
        _consumer_wait_num = 0;
    }

    void Enqueue(const T& in)//生产者接口
    {
        pthread_mutex_lock(&_mutex);
        while(IsFull())
        {
            //生产进程去等待，实在临界区中休眠，目前还持有锁。
            //线程唤醒必须重新竞争_mutex锁，方可返回
            _productor_wait_num++;
            pthread_cond_wait(&_product_cond, &_mutex);
            _productor_wait_num--;
        }
        //进行生产
        //_block_queue.push(move(in));
        _block_queue.push(in);
        //通知消费者消费
        if(_consumer_wait_num>0)
        {
            pthread_cond_signal(&_consum_cond);
        }
        pthread_mutex_unlock(&_mutex);
    }

    void Pop(T* out)//消费者接口
    {
        
        pthread_mutex_lock(&_mutex);
        while(IsEmpty())
        {
            //消费进程去等待，实在临界区中休眠，目前还持有锁。
            _consumer_wait_num++;
            pthread_cond_wait(&_consum_cond, &_mutex);
            _consumer_wait_num--;
        }
        //进行消费
        *out = _block_queue.front();
        _block_queue.pop();
        if(_productor_wait_num>0)
        {
            pthread_cond_signal(&_product_cond);
        }
        pthread_mutex_unlock(&_mutex);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_product_cond);
        pthread_cond_destroy(&_consum_cond);
    }

private:
    bool IsFull()
    {
        return _block_queue.size() == _cap;
    }

    bool IsEmpty()
    {
        return _block_queue.size() == 0;
    }

    queue<T> _block_queue;  //阻塞队列
    int _cap;   //总上限
    pthread_mutex_t _mutex; //保护锁
    pthread_cond_t _product_cond;   //生产条件变量
    pthread_cond_t _consum_cond;    //消费条件变量

    int _productor_wait_num;  //等待的生产者数量
    int _consumer_wait_num; //等待的消费者数量
};

#endif